package dolf.objects;

public class Intersect {
	/* Intersection of two Straight ones*/
	static Point StraightXStraight(Point p1, Vector d1, Point p2, Vector d2){
		/*
	 	( d1 	d2) (x)		(p2.x - 	p1.x	)  	
	 	(		  ) ( )	=	(					)
	 	( d1 	d2) (y)		(p2.y -		p1.y	)
	 */
	 
		double det = d1.getX()*d2.getY() - d1.getY()*d2.getX(); 
		if(Math.abs(det)<1.0E-13){ // Fall Parallel oder Identisch
			System.err.println("Parallel oder Identische Gerade");
			return null; // es exisitiert kein schnittpunkt
		} else {
		// Berechntet Schnittpunkt s;
			double x = ((p2.getX() - p1.getX()) * d2.getY() - (p2.getY() - p1.getY()) * d2.getX()) / det;
			Point S = p1.add(d1.multS(x));
			return S; 
		}
	}
	/* Intersection of a Line and a Straight one*/
	static Point LineXStraight(LineObject l, Point p, Vector v){
		Point erg = StraightXStraight(l.getPosition(),l.getDirection(),p,v);
		if(erg != null && l.IntersectBetweenBounds(erg)){
			return erg;
		}
		return null; 
	}
	
	/* Intersection of two Lines*/
	static Point LineXLine(LineObject l1, LineObject l2){
		Point erg = StraightXStraight(l1.getPosition(),l1.getDirection(),l2.getPosition(),l2.getDirection());
		if(l1.IntersectBetweenBounds(erg) && l2.IntersectBetweenBounds(erg)){
			return erg;
		}
		return null; 
	}
	
	/* Intersection of a Straight(p2, d) and a Circle (p1 , radius)*/
	public static Point[] CircleXStraight(Point p1, int radius, Point p2, Vector d){
		Point[] erg;
		Point t = p2.sub(p1);
		double c = (t.getX()*t.getX()+t.getY()*t.getY()-radius*radius);
		double b = 2*d.getX()*t.getX()+ 2*d.getY()*t.getY();
		double a = d.getX()*d.getX()+d.getY()*d.getY();
		double w = b*b - 4 * a * c;
		if(Math.abs(w)<1.0E-13){
			erg = new Point[1];
			double k = -b/(2*a);
			erg[0] = new Point(p2.getX()+k*d.getX(),p2.getY()+k*d.getY());			
			return erg; 
		}
		if(w < 0){
			return null;
		}
		erg = new Point[2];
		double k1 = (-b+Math.sqrt(w))/(2*a);
		double k2 = (-b-Math.sqrt(w))/(2*a);
		erg[0] = new Point(p2.getX()+k1*d.getX(),p2.getY()+k1*d.getY());			
		erg[1] = new Point(p2.getX()+k2*d.getX(),p2.getY()+k2*d.getY());			
		return erg;
	}
	/* Intersection of a Straight(p2, d) and a CircleObject c */
	static Point[] CircleXStraight(CircleObject c, Point p, Vector d){
		return Intersect.CircleXStraight(c.getPosition(), c.getRadius(), p, d);
	}
	/* Intersection of a CircleObject, LineObject l */
	static Point[] CircleXLine(CircleObject c, LineObject l){
		Point[] erg = Intersect.CircleXStraight(c.getPosition(), c.getRadius(), l.getPosition(), l.getDirection());
		if(erg == null){
			return null;
		}
		int z = 0;
		for(int i = 0; i < erg.length; i++){
			if(l.IntersectBetweenBounds(erg[i])){
				z += i+1;
			}
		}
		switch(z){
			case 0:
				erg = null;
				break;
			case 1:
				Point tmp = erg[0];
				erg = new Point[1];
				erg[0] = tmp;
				break;
			case 2:
				tmp = erg[1];
				erg = new Point[1];
				erg[0] = tmp;
		}
		return erg;
	}
	static Point[] CircleXLine(Point p, int radius, LineObject l){
		return Intersect.CircleXLine(new CircleObject(p,radius,false), l);
	}
	/*
	 * Schnittpunkte im Array 
	 * liegt ein Kreis im Anderen ist im Array zwei O !!!!;
	 * null wenn sich beide Kreise nicht schneiden
	 * */	
	public static Point[] CircleXCircle(CircleObject c1, CircleObject c2){
		if(c1.getPosition().getDist(c2.getPosition()) < Math.abs(c2.getRadius()-c1.getRadius())){
			Point[] erg = new Point[2];
			erg[0] = new Point(0,0);
			erg[1] = erg[0];
			return erg;
		}
		Vector v =  c2.getPosition().sub(c1.getPosition()).multS((double)c1.getRadius()/(c1.getRadius()+c2.getRadius()));
		Point p = c1.getPosition().add(v);
		System.out.println("mitte " +p.print());
		v = v.getNormVec();
		return Intersect.CircleXStraight(c1, p, v);
	}
}
